package ua.org.extjsbuilder.parser.scanner;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;
import ua.org.extjsbuilder.parser.IToken;
import ua.org.extjsbuilder.parser.ITokenList;
import ua.org.extjsbuilder.parser.runtime.CommentToken;
import ua.org.extjsbuilder.parser.runtime.JSGlobalToken;
import ua.org.extjsbuilder.parser.runtime.NumberLiteralToken;
import ua.org.extjsbuilder.parser.runtime.RegexpLiteralToken;
import ua.org.extjsbuilder.parser.runtime.StringLiteralToken;
import ua.org.extjsbuilder.parser.runtime.UnparsedToken;

public class CommentsAndLiteralsScannerTestCase extends TestCase {
	private static final String MOCK_PKG = "ua/org/extjsbuilder/parser/mock/";
	
	private static final Class<?>[] FIRST_SEQUENCE = new Class<?>[]{
		UnparsedToken.class,NumberLiteralToken.class,UnparsedToken.class,CommentToken.class,
		UnparsedToken.class,UnparsedToken.class,UnparsedToken.class,UnparsedToken.class,
		StringLiteralToken.class,UnparsedToken.class,UnparsedToken.class,UnparsedToken.class,
		CommentToken.class,CommentToken.class,CommentToken.class,CommentToken.class,
		UnparsedToken.class,UnparsedToken.class,RegexpLiteralToken.class,UnparsedToken.class,
		UnparsedToken.class,UnparsedToken.class,CommentToken.class,UnparsedToken.class,
		UnparsedToken.class,UnparsedToken.class,UnparsedToken.class,NumberLiteralToken.class,
		UnparsedToken.class};	
	
	private static final Class<?>[] SECOND_SEQUENCE = new Class<?>[]{
		CommentToken.class,UnparsedToken.class,UnparsedToken.class,NumberLiteralToken.class,
		UnparsedToken.class,UnparsedToken.class,StringLiteralToken.class,UnparsedToken.class,
		UnparsedToken.class,StringLiteralToken.class,UnparsedToken.class,UnparsedToken.class,
		NumberLiteralToken.class,UnparsedToken.class,UnparsedToken.class,UnparsedToken.class};

	
	public void testScan() throws Exception{
		List<IToken> result = getResultForResource("test1.js");
		assertEquals(30, result.size());
		result.remove(0);
		assertEquals(FIRST_SEQUENCE,result);
		
		List<IToken> result2 = getResultForResource("test5.js");
		assertEquals(17, result2.size());
		result2.remove(0);
		assertEquals(SECOND_SEQUENCE,result2);
	}
	
	protected void assertEquals(Class<?>[] expected, List<IToken> actual){
		int i=0;
		for(IToken tok : actual){
			if(i>=expected.length){
				fail();
			}
			assertEquals("Expected "+expected[i].getName()+
					" but was "+tok.getClass().getName()+
					" in position "+i,expected[i++], tok.getClass());
		}
		if(i<expected.length){
			fail();
		}
	}

	private List<IToken> getResultForResource(String resource) throws IOException {
		ITokenList global = getGlobalFor(resource);
		global.scan(new LinesScanner());
		global.scan(new CommentsAndLiteralsScanner());
		return asStdList(global);
	}
	
	private List<IToken> asStdList(ITokenList global) {
		List<IToken> result = new ArrayList<IToken>();
		IToken t = global.getHead();
		while(t!=null){
			result.add(t);
			t = t.getNext();
		}
		return result;
	}

	private ITokenList getGlobalFor(String resource) throws IOException{
		return new JSGlobalToken(new InputStreamReader(
				getStream(resource)));
	}
	
	private InputStream getStream(String resource) {
		return getClass().getClassLoader()
			.getResourceAsStream(MOCK_PKG+resource);
	}
}
